/**
 * 
 */
package com.training.spring.jsf.phase.listener;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 189833
 *
 */
public class SpringTrainingPhaseListener
    implements
    PhaseListener {

    /**
     * 
     */
    private static final long   serialVersionUID = 1L;

    private static final Logger LOG              = LoggerFactory.getLogger( SpringTrainingPhaseListener.class );
    private static final String KEY              = SpringTrainingPhaseListener.class.getName() + "_ID_";

    public SpringTrainingPhaseListener() {

    }

    public void afterPhase(PhaseEvent phaseEvent) {
        FacesContext facesContext = phaseEvent.getFacesContext();
        facesContext.getExternalContext().log( " AFTER - " + phaseEvent.getPhaseId().toString() );

        if ( LOG.isInfoEnabled() ) {
            Date end = new Date();
            Map map = facesContext.getExternalContext().getRequestMap();
            map.put( KEY + phaseEvent.getPhaseId().getOrdinal() + "E",
                     end );

            if ( LOG.isTraceEnabled() ) {
                LOG.trace( " AFTER PHASE :" + phaseEvent.getPhaseId().toString() + " Time=" + end.getTime() );
            }

            if ( LOG.isDebugEnabled() ) {
                Date start = (Date) map.get( KEY + phaseEvent.getPhaseId().getOrdinal() + "S" );
                LOG.debug( " Phase " + phaseEvent.getPhaseId().toString() + " needs " + (end.getTime() - start.getTime() + " milliseconds") );
            }

            if ( phaseEvent.getPhaseId().getOrdinal() == 6 ) {
                Date start = (Date) map.get( KEY + "1S" );
                if ( start != null ) {
                    LOG.info( " Total response time : " + (end.getTime() - start.getTime() + " milliseconds") );
                }
            }

            for ( Iterator msgIter = facesContext.getMessages(); msgIter.hasNext(); ) {
                FacesMessage msg = (FacesMessage) msgIter.next();
                LOG.info( MessageFormat.format( " Global Faces message found." + "\n  Severity : {0}" + "\n  Summary  : {1} \n  Detail   : {2}",
                                                new Object[]{msg.getSeverity(), msg.getSummary(), msg.getDetail()} ) );
            }
        }

        if ( phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE ) {
            //DebugUtil.printTree(facesContext.getViewRoot(), System.out);
            facesContext.getExternalContext().log( " Done with Request!\n" );
        }
    }

    public void beforePhase(PhaseEvent phaseEvent) {

        FacesContext facesContext = phaseEvent.getFacesContext();

        //        String requestURL = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getRequestURL().toString();
        //        String redirect = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getParameter( "redirect" );
        //
        //        LOG.info( "Request URL : " + ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getRequestURL().toString() );
        //        LOG.info( "Session obj : " + facesContext.getExternalContext().getSession( false ) );
        //        LOG.info( "View Root : " + facesContext.getViewRoot() );
        //      if(!(redirect!=null && redirect.equals(true)) && (requestURL.endsWith("expired.xhtml") || requestURL.endsWith("login.xhtml"))){
        //          
        //          LOG.info("Session obj : "+facesContext.getExternalContext().getSession(false));
        //          LOG.info("View Root : "+facesContext.getViewRoot());
        //          if(facesContext.getExternalContext().getSession(false)== null && (facesContext.getViewRoot()== null || StringUtils.isBlank(facesContext.getViewRoot().getViewId()))){
        //              try {
        //                  LOG.info("request context path "+facesContext.getExternalContext().getRequestContextPath());
        //                  LOG.info("................................................Invoking redirect......................................................");
        //                  facesContext.getExternalContext().redirect(facesContext.getExternalContext().getRequestContextPath()+"/faces/app/mainpage.xhtml?redirect=true");
        //              } catch (Exception e) {
        //                  LOG.error("IOException occurred while redirecting to /ravas/faces/app/mainpage.xhtml ", e);
        //              }
        //          }
        //      }

        if ( phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE ) {
            //            setNoCacheResponseHeader( facesContext );
        }

        if ( phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW ) {
            facesContext.getExternalContext().log( " Processing new  Request!" );
        }

        facesContext.getExternalContext().log( " BEFORE - " + phaseEvent.getPhaseId().toString() );

        if ( LOG.isInfoEnabled() ) {
            Date start = null;
            Map map = null;
            PhaseId phaseId = phaseEvent.getPhaseId();
            if ( LOG.isDebugEnabled() || phaseId.getOrdinal() == 1 ) {

                ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

                if ( LOG.isTraceEnabled() && PhaseId.RESTORE_VIEW == phaseId ) {
                    // this is before restoreView
                    Map params = externalContext.getRequestParameterMap();
                    for ( Object key : params.keySet() ) {
                        LOG.trace( " Param : \"" + key + "\" = \"" + params.get( key ) + "\"" );
                    }
                }

                start = new Date();
                map = externalContext.getRequestMap();
                map.put( KEY + phaseId.getOrdinal() + "S",
                         start );
            }

            if ( LOG.isDebugEnabled() ) {
                Date end = null;
                int ordinal = phaseId.getOrdinal();
                while ( end == null && ordinal > 0 ) {
                    end = (Date) map.get( KEY + --ordinal + "E" );
                }
                if ( end != null ) {
                    LOG.debug( " Time between phases " + ordinal + " and " + phaseId.getOrdinal() + ": " + (start.getTime() - end.getTime()) + " milliseconds" );
                }
            }
            if ( LOG.isTraceEnabled() ) {
                LOG.trace( " BEFORE PHASE :" + phaseId.toString() + " Time=" + start.getTime() );
            }
        }
    }

    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }

    //    private void setNoCacheResponseHeader(FacesContext facesContext) {
    //        HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
    //        response.addHeader( "Pragma",
    //                            "no-cache" );
    //        response.addHeader( "Cache-Control",
    //                            "no-cache" );
    //        // Stronger according to blog comment below that references HTTP spec
    //        response.addHeader( "Cache-Control",
    //                            "no-store" );
    //        response.addHeader( "Cache-Control",
    //                            "must-revalidate" );
    //        // some date in the past
    //        response.addHeader( "Expires",
    //                            "Mon, 8 Aug 2005 10:00:00 GMT" );
    //    }

}
